# 用于解析串口数据包，实验用

import sys
from typing import Dict
from typing import List, Optional

# 添加截包解析
class PacketSniffer:
    """基于包头包尾的二进制数据流分割器（需在HexPacketSniffer前定义）"""
    def __init__(self):
        self.buffer = bytearray()
        self.header = 0xAA  # 包头
        self.footer = 0x2F   # 包尾

    def feed(self, data: bytes) -> None:
        self.buffer.extend(data)

    def extract(self) -> List[bytes]:
        packets = []
        while True:
            header_pos = self.buffer.find(self.header)
            if header_pos == -1: break
            
            remaining = self.buffer[header_pos:]
            footer_pos = remaining.find(self.footer)
            if footer_pos == -1: break
            
            packet_end = header_pos + footer_pos + 1
            packets.append(self.buffer[header_pos:packet_end])
            self.buffer = self.buffer[packet_end:]
        return packets

class HexPacketSniffer:
    """增强型十六进制字符串数据包截取器"""
    def __init__(self):
        self.raw_buffer = ""
        self.byte_sniffer = PacketSniffer()  # 现在可以正确引用
    
    def feed_str(self, hex_str: str) -> None:
        cleaned = hex_str.replace(" ", "").strip()
        if not cleaned: return
        
        # 处理奇数长度残留
        if self.raw_buffer:
            cleaned = self.raw_buffer + cleaned
            self.raw_buffer = ""
        
        if len(cleaned) % 2 != 0:
            self.raw_buffer = cleaned[-1]
            cleaned = cleaned[:-1]
        
        try:
            self.byte_sniffer.feed(bytes.fromhex(cleaned))
        except ValueError as e:
            print(f"HEX转换错误: {str(e)}")

    def extract_packets(self) -> List[bytes]:
        return self.byte_sniffer.extract()

def calculate_checksum(data: bytes) -> int:
    """统一校验码计算：包头到校验码前所有字节的和取低8位"""
    # 校验码位置始终是倒数第二字节，包尾是最后一字节
    return sum(data[:-2]) % 256  # 包头到校验码前所有字节

def parse_response(data: bytes) -> Dict:
    """统一响应解析入口"""
    # 基础校验
    if len(data) < 3:
        raise ValueError(f"数据长度过短 ({len(data)} bytes)")
    if data[0] != 0xAA or data[-1] != 0x2F:
        raise ValueError(f"包头/包尾错误 (头:0x{data[0]:02X}, 尾:0x{data[-1]:02X})")
    
    # 计算并验证校验码
    expected_checksum = calculate_checksum(data)
    received_checksum = data[-2]
    if expected_checksum != received_checksum:
        raise ValueError(f"校验码错误 (计算:0x{expected_checksum:02X}, 接收:0x{received_checksum:02X})")
    
    # 获取命令类型
    cmd = data[2]
    parser = {
        0x20: parse_cmd20,
    }.get(cmd, lambda x: {"error": f"未知命令 0x{cmd:02X}"})
    
    return parser(data)

# ------------------------- 各命令解析器 -------------------------
    """解析0X20响应：一键发送重量"""
def parse_cmd20(data: bytes) -> Dict:
    if len(data) != 15:
        raise ValueError("数据长度必须为15字节")

    # 校验包头包尾
    if data[0] != 0xAA or data[-1] != 0x2F:
        raise ValueError("无效的包头或包尾")
    
    """计算称重数据包校验码计算验证码"""
    # 范围：第1字节（包头）到第13字节（皮重结束）
    checksum_bytes = data[0:13]
    checksum =sum(checksum_bytes) % 256

    # # 验证校验码
    if checksum != data[-2]:
        raise ValueError(f"验证码错误，计算值0x{checksum:02X}，接收值0x{data[-2]:02X}")

    # 解析字段
    length = data[1]
    command = data[2]
    
    # 解析符号和单位
    sign_unit = data[3]
    if sign_unit == 0x81:
        sign, unit = "+", "KG"
    elif sign_unit == 0x01:
        sign, unit = "-", "KG"
    else:
        sign, unit = "", "UNKNOWN"
    
    # 解析数值
    decimal_places = data[4]
    net_weight = int.from_bytes(data[5:9], "big")
    stability = "稳定" if data[9] == 0x0A else "不稳定"
    tare = int.from_bytes(data[10:13], "big")

    # 应用小数位
    net_weight = (-1 if sign == "-" else 1) * net_weight / (10**decimal_places)
    tare = tare / (10**decimal_places)

    return {
        "作用":"命令1——0x20一键发送重量",
        # "包头": "0xAA",
        # "长度": length,
        # "命令": f"0x{command:02X}",
        # "符号": sign,
        # "单位": unit,
        # "小数位": decimal_places,
        "净重": f"{net_weight:.{decimal_places}f} {unit}",
        "稳定状态": stability,
        "皮重": f"{tare:.{decimal_places}f} {unit}",
        # "验证码": f"0x{data[-2]:02X}",
        "解析数据": f"{sign}{net_weight:.{decimal_places}f} {unit}",
        # "包尾": "0x2F"
    }

# ------------------------- 快速测试 -------------------------
if __name__ == "__main__":
    hex_str = " AA 0B 20 81 03 00 00 02 0D 0A 00 00 00 72 2F "  # 20
    
    sniffer = HexPacketSniffer()
    sniffer.feed_str(hex_str)

    print("捕获数据包:")
    test_cases = []
    for pkt in sniffer.extract_packets():
        pkt_str = pkt.hex(' ').upper()
        print(pkt_str)
        test_cases.append(pkt_str)
    
    if sniffer.byte_sniffer.buffer:
        print(f"残留数据: {sniffer.byte_sniffer.buffer.hex()}")


    for hex_str in test_cases:
    # for pkt in sniffer.extract_packets():
        print("\n" + "="*50)
        print(f"测试数据: {hex_str}")
        try:
            # 转换数据
            data = bytes.fromhex(hex_str.replace(" ", ""))
            result = parse_response(data)
            # 打印结果
            for key, value in result.items():
                print(f"{key:>12}: {value}")
        except Exception as e:
            print(f"解析失败: {str(e)}")
